import json

from django.http import JsonResponse
from django.shortcuts import render

# Create your views here.
"""
第三方登录的步骤：
1.qq互联开发平台申请成为开发者（可以不用做）
2.qq互联创建应用（可以不用做）
3.按照文档开发（看文档）

3.1准备工作
# QQ登录参数
# 我们申请的 客户端id
QQ_CLIENT_ID = '101474184'
# 我们申请的 客户端秘钥
QQ_CLIENT_SECRET = 'c6ce949e04e12ecc909ae6a8b09b637c'
# 我们申请时添加的: 登录成功后回调的路径
QQ_REDIRECT_URI = 'http://www.meiduo.site:8080/oauth_callback.html'


3.2 放置qq图标（目的：让我们点击请求图标来实现第三方登录）----前端已经做好了

3.3 根据oauth2.0 来获取code 和 token              ----我们要做的
    对于应用而言，需要进行两步：
    1.获取Authorization Code:      表面是一个链接，实质是需要用户同意，然后获取code
    2.通过Authorization Code 获取Access Token

3.4 通过token换取 openid                         -----我们要做的
    opeid是此网站唯一对应用户身份的标识，网站可将此ID进行存储便于用户下次登录时辨识身份，
    或将其与用户在网站上的原有账号进行绑定。

把openid和用户信息进行一一对应的绑定

生成用户绑定链接---------->获取code---------->获取token----------->获取openid--------->保存openid
"""

"""
生成用户绑定链接

前端：当用户点击qq登录的时候，前端发送axios请求

后端：
    请求：     
    业务逻辑：   调用QQLoginTool生成跳转链接
    响应：      返回跳转链接{"code":0,"qq_login_url":"http://xxx"}  
    路由：      GET qq/authorization/
    步骤：
            1.生成QQLoginTool 实例对象
            2.调用对象方法生成跳转链接
            3.返回响应
"""
from QQLoginTool.QQtool import OAuthQQ
from django.views import View
from meiduo_mall import settings
class QQLoginURLView(View):
    def get(self,request):
        # 1.生成QQLoginTool 实例对象
        # client_id=None,  appid
        # client_secret=None,  appsecret
        # redirect_uri=None,   用户同意后跳转的页面
        # state=None
        qq=OAuthQQ(client_id=settings.QQ_CLIENT_ID,
                   client_secret=settings.QQ_CLIENT_SECRET,
                   redirect_uri=settings.QQ_REDIRECT_URI,
                   state='xxxx')
        # 2.调用对象方法生成跳转链接
        qq_login_url=qq.get_qq_url()
        # 3.返回响应
        return JsonResponse({'code':0,'errmsg':'ok','login_url':qq_login_url})


"""
需求：获取code ，通过code获取token 再通过token获取openid

前端:
    获取 用户同意登录的code，将code发送给后端
后端：
    请求          获取code  
    业务逻辑       通过code获取token 再通过token获取openid
                  根据openid进行判断
                  如果没有绑定过，则需要绑定
                  如果绑定过则直接登录
    响应
    路由           GET  oauth_callback/?code=xxxx
    步骤          
        1.获取code
        2.通过code获取token
        3.通过token获取openid
        4.根据openid进行判断
        5.如果没有绑定过，则需要绑定 
        6.如果绑定过则直接登录
"""
from apps.oauth.models import OAuthQQUser
from django.contrib.auth import login
from apps.users.models import User
class OauthQQView(View):
    def get(self,request):
        # 1.获取code
        #'4FC5871E126F25F5B7F6FA043C418B04'
        code=request.GET.get('code')
        if code is None:
            return JsonResponse({'code':400,'errmsg':'参数不全'})
        # 2.通过code获取token
        qq = OAuthQQ(client_id=settings.QQ_CLIENT_ID,
                   client_secret=settings.QQ_CLIENT_SECRET,
                   redirect_uri=settings.QQ_REDIRECT_URI,
                   state='xxxx')
        #'CFA85231224ADC525090F878D8498D7E'
        #'520E1F253ADC977AAB9802FD71C76A2E'
        token=qq.get_access_token(code)
        # 3.通过token获取openid
        #'AD2493FCADF940F7132B5BEA37805C78'
        #'AD2493FCADF940F7132B5BEA37805C78'
        openid=qq.get_open_id(token)
        # 4.根据openid进行判断
        try:
            qquser=OAuthQQUser.objects.get(openid=openid)
        # 5.如果没有绑定过，则需要绑定
        except OAuthQQUser.DoesNotExist:
            """
            封装的思想
                所谓的封装的思想其实就是 把一些实现了特定功能的代码封装成一个函数（方法）
            封装的目的
                解耦  -----当需求发生改变时，对代码的影响比较小
            封装的步骤
                1.把要封装的代码 定义到一个函数（方法）中
                2.优化封装后的代码
                3。验证封装的代码
            """
            #对openid加密
            from apps.oauth.uitls import generic_openid
            access_token = generic_openid(openid)
            response = JsonResponse({'code':400,'access_token':access_token})
            return response
        # 6.如果绑定过则直接登录
        else:
            login(request,qquser.user)
            response = JsonResponse({'code':0,'errmsg':'ok'})
            response.set_cookie('username',qquser.user.username)

            return response

    def post(self,request):
        # 1.接收请求
        data=json.loads(request.body.decode())
        # 2.获取请求参数 openid
        mobile=data.get('mobile')
        password = data.get('password')
        sms_code = data.get('sms_code')
        access_token = data.get('access_token')
        #需要进行验证
        # 2.校验参数
        # 判断参数是否齐全
        import re
        if not all([mobile, password, sms_code]):
            return JsonResponse({'code': 400,
                                      'errmsg': '缺少必传参数'})

        # 判断手机号是否合法
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return JsonResponse({'code': 400,
                                      'errmsg': '请输入正确的手机号码'})

        # 判断密码是否合格
        if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
            return JsonResponse({'code': 400,
                                      'errmsg': '请输入8-20位的密码'})
        from django_redis import get_redis_connection
        redis_conn = get_redis_connection('code')
        sms_code_server = redis_conn.get(mobile)
        # 判断获取出来的有没有:
        if sms_code_server is None:
            # 如果没有, 直接返回:
            return JsonResponse({'code': 400,
                                      'errmsg': '验证码失效'})
        # 如果有, 则进行判断:
        if sms_code != sms_code_server.decode():
            # 如果不匹配, 则直接返回:
            return JsonResponse({'code': 400,
                                      'errmsg': '输入的验证码有误'})

            # 调用我们自定义的函数, 检验传入的 access_token 是否正确:
        # 添加对access_token 解密
        from apps.oauth.uitls import check_access_token
        openid = check_access_token(access_token)
            # 3.根据手机号进行用户信息查询
        try:
            user=User.objects.get(mobile=mobile)
        # 5.查询到用户手机号没有注册，我们就创建一个user信息，然后再绑定
        except User.DoesNotExist:
            user=User.objects.create_user(username=mobile,mobile=mobile,password=password)
        # 4.查询到手机号已经注册，验证密码，密码正确就可以直接进行绑定 用户和openid信息
        else:
            if not user.check_password(password):
                return JsonResponse({'code':400,'errmsg':'账号或密码错误'})
        OAuthQQUser.objects.create(user=user,openid=openid)
        # 6.完成状态保持
        login(request,user)
        # 7.返回响应
        response=JsonResponse({'code':0,'errmsg':'ok'})

        response.set_cookie('username',user.username)
        return response

"""
需求：绑定账号信息
    QQ（openid） 和美多的账号信息

前端：用户输入 手机号，密码，短信验证码之后，发送axios请求，请求需要携带 mobile,password,sms_code,access_token(openid)

后端：
    请求：接收请求，获取请求参数
    业务逻辑：绑定完成状态保持
    响应：返回code=0，跳转到首页
    路由：POST oauth_callback/
    步骤：
        1.接收请求
        2.获取请求参数
        3.根据手机号进行用户信息查询
        4.查询到手机号已经注册，验证密码，密码正确就可以直接进行绑定 用户和openid信息
        5.查询到用户手机号没有注册，我们就创建一个user信息，然后再绑定
        6.完成状态保持
        7.返回响应
"""

##############itsdangerous 数据加密###############
#1.导入itsdangerous的类
#2.创建类的实例对象
#3.加密数据
#
from meiduo_mall import settings
#1.导入itsdangerous的类
from itsdangerous import URLSafeTimedSerializer as Serializer
#2.创建类的实例对象
s=Serializer(settings.SECRET_KEY)
#3.加密数据
token=s.dumps({'openid':'123456'})
#解密数据
s.loads(token,max_age=60*60)